#include "threadPool.h"



//注册程序
int registerUser(int netfd, MYSQL *mysql, char *userName, char *passWord)
{
    //char userName[1024] = {0};
    //char passWord[1024] = {0};
    char salt[21] = {0};
    char *encrypted = NULL;
    //recv(netfd, userName, sizeof(userName)-1, MSG_NOSIGNAL);//接收用户名
    //recv(netfd, passWord, sizeof(passWord)-1, MSG_NOSIGNAL);//接受密码
    randomSaltValue(salt);//生成随机盐值函数
    printf("salt = %s\n", salt);
    encrypted = crypt(passWord, salt);//生成密文
    if(encrypted == NULL)
    {
        printf("加密失败，注册失败。\n");
        return -1;
    }
    printf("encrypted = %s\n", encrypted);//打印密文
    char sql[1024];

    userName[strcspn(userName, "\n")] = '\0';
    salt[strcspn(salt, "\n")] = '\0';
    encrypted[strcspn(encrypted, "\n")] = '\0';

    snprintf(sql, sizeof(sql), "insert into user_excel (username, salt, encrypted_password, is_deleted) values ('%s', '%s', '%s', 0);", userName, salt, encrypted);

    if(mysql_query(mysql, sql) == 0)
    {
        send(netfd, "0", 2, MSG_NOSIGNAL);
        printf("用户%s注册成功。\n", userName);
        func_mkdir(userName,NULL, "/", mysql);
    }
    else
    {
        send(netfd, "-1", 3, MSG_NOSIGNAL);
        fprintf(stderr, "注册失败：%s\n", mysql_error(mysql));
    }
    return 0;
}

//登录程序
//
int userLogin(int netfd, MYSQL *mysql, char *userName)
{
    // char userName[1024] = {0};
    //根据用户名查询盐值和密文
    char sql[1024];
    userName[strcspn(userName, "\n")] = '\0';
    snprintf(sql, sizeof(sql), "select salt ,encrypted_password from user_excel where username = '%s' and is_deleted=0;",userName);
    if(mysql_query(mysql, sql) != 0)
    {
        //send(netfd, "查询失败。\n");
        printf("查无此人。\n");
        return -1;
    }
    //查询成功，此时有张表
    MYSQL_RES *res = mysql_store_result(mysql);//读表格
    MYSQL_ROW row = mysql_fetch_row(res);

    if(!row)
    {
        //send(netfd, "-1", 2, 0);
        mysql_free_result(res);
        return -1;
    }
    char *salt = row[0];
    char *encrypted = row[1];
    printf("salt=%s",salt);
    //发送盐值给client
    send(netfd, salt, strlen(salt), MSG_NOSIGNAL);

    //等待客户端密文
    char encryptedInput[512] = {0};
    ssize_t ret = recv(netfd, encryptedInput, sizeof(encryptedInput)-1, MSG_NOSIGNAL);
    if(ret <= 0)
    {
        //send(netfd, "-1", 2, 0);
        printf("密文接收失败。\n");
        return -1;
    }
    encryptedInput[ret] = '\0';

    //比对密文
    if(strcmp(encryptedInput, encrypted) == 0)
    {
        send(netfd, "0", 2, MSG_NOSIGNAL);
        printf("客户端%s登陆成功。\n",userName);
        mysql_free_result(res);
        return 0;
    }
    else
    {
        send(netfd, "-1", 3, MSG_NOSIGNAL);
        printf("客户端%s登陆失败。\n", userName);
        mysql_free_result(res);
        return -1;
    }
}



void *threadFunc(void *arg)
{
    threadPool_t *pthreadPool = (threadPool_t *)arg;
    while(1)
    {
        pthread_mutex_lock(&pthreadPool->mutex);
        while(pthreadPool->exitFlag == 0 && pthreadPool->taskQueue.queueSize <= 0)
        {
            pthread_cond_wait(&pthreadPool->cond, &pthreadPool->mutex);
        }
        if(pthreadPool->exitFlag == 1)
        {
            printf("I am worker. I am going to exit!\n");
            pthread_mutex_unlock(&pthreadPool->mutex);
            pthread_exit(NULL);
        }
        int netfd = pthreadPool->taskQueue.pFront->netfd;
        printf("I am worker. netfd = %d\n", netfd);
        deQueue(&pthreadPool->taskQueue);
        pthread_mutex_unlock(&pthreadPool->mutex);


        pthread_mutex_lock(&pthreadPool->mutex);
        MYSQL *mysql = mysql_init(NULL);//初始化
        if(mysql == NULL)
        {
            fprintf(stderr, "mysql_init() failed\n");
            exit(-1);
        }
        //建立连接
        MYSQL *ret = mysql_real_connect(mysql,
                                        "localhost",
                                        "root",
                                        "123",//改成自己的
                                        "wp_v3",//改成自己的
                                        0,NULL,0);
        pthread_mutex_unlock(&pthreadPool->mutex);
        if(ret == NULL)
        {
            fprintf(stderr, "%s:%s\n", "mysql_real_connect", mysql_error(mysql));
            mysql_close(mysql);
            exit(-1);
        }
        char userName[1024] = {0};
        char passWord[1024] = {0};
        while(1)
        {
            //首先，先识别是注册还是登录, 1是注册， 2是登录
            char identify[20] = {0};
            ssize_t ret1 = recv(netfd, identify,sizeof(identify), MSG_NOSIGNAL);
            printf("identify=%s\n",identify);
            if(ret1 <= 0)
            {
                printf("识别失败。");
                continue;
            }
            printf("1\n");
            recv(netfd, userName, sizeof(userName)-1, MSG_NOSIGNAL);
            printf("1\n");
            printf("userName=%s\n",userName);
            int ret= recv(netfd, passWord, sizeof(passWord)-1, MSG_NOSIGNAL);
            if (ret == -1) {
                perror("send failed");
                exit(1);
            }
            identify[strcspn(identify, "\n")] = '\0';
            printf("identify=%s\n",identify);
            //识别成功
            if(strcmp("1", identify) == 0)
            {
                printf("识别成功，将进行注册。\n");
                //执行注册程序
                registerUser(netfd,mysql, userName, passWord);
                break;
            }
            else if(strcmp("2", identify) == 0)
            {
                printf("识别成功，将进行登录。\n");
                //执行登录程序
                int a=userLogin(netfd, mysql, userName);
                if(a==-1){
                    exit(-1);
                    //continue;
                }
                break;
            }
            else
            {
                printf("收到未知标识:%s\n",identify);
                printf("请重新输入。");
                continue;
            }
        }


        numStack_t stack;
        numStackInit(&stack);
        int empty_num = 0;
        char sql666[2000]={0};
        printf("查找当前用户根目录位置并压入栈中\n");
        sprintf(sql666,"select * from file_excel where path = '/'  and user_name = '%s' ;",userName);
        mysql_query(mysql,sql666);
        MYSQL_RES *hhh = mysql_store_result(mysql);//得到查询结果                                     
        MYSQL_ROW row=mysql_fetch_row(hhh);//取出查询结果的一行
        int will_in_stack=atoi(row[0]);
        printf("/ in file_excel index is %d\n",will_in_stack);
        pushStack(&stack,will_in_stack);
        //mysql_free_result(hhh);
        printf("111111111111111111111\n");




        //cd ls pwd puts gets mkdir rmdir 
        while(1)
        {
            char hashValue[50] = {0};
            char temp[1024] = {0};
            train_t train;
            memset(&train, 0, sizeof(train));

            ssize_t ret = recv(netfd, &train.flag, sizeof(train.flag), MSG_NOSIGNAL);
            if(empty_num > 2)
            {
                break;
            }
            if(ret <= 0)
            {
                ++empty_num;
                perror("recv failed.\n");
                continue;
            }

            //cd 进入某文件夹
            if(train.flag == 1)
            {
                char path[1024] = {0};
                memset(&train, 0, sizeof(train));
                recv(netfd, &train.length, sizeof(train.length), MSG_NOSIGNAL);
                recv(netfd, train.data, train.length, MSG_NOSIGNAL);
                strcpy(path, train.data);
                printf("----------path; %s\n",path);
                ssize_t ret = func_cd(path, &stack, mysql, userName);
                if(ret == 0)
                {
                    send(netfd, "0", 2, MSG_NOSIGNAL);
                }
                else
                {
                    send(netfd, "-1", 3, MSG_NOSIGNAL);
                }
            }

            //ls 展示当前目录
            else if(train.flag == 2)
            {
                ssize_t ret =func_ls(temp, &stack, mysql);
                if(ret == 0)
                {
                    send(netfd, temp, strlen(temp), MSG_NOSIGNAL);
                }
                else
                {
                    send(netfd, "-1", 3, MSG_NOSIGNAL);
                }
            }

            //我方gets 客户端puts
            else if(train.flag == 3)
            {
                bzero(hashValue,sizeof(hashValue));
                //接收客户端发的哈希值再传进函数里面
                char fileName[40] = {0};
                recv(netfd, &train.length, sizeof(train.length), MSG_WAITALL);
                recv(netfd, train.data, train.length,MSG_WAITALL);

                recv(netfd, &train.length, sizeof(train.length), MSG_WAITALL);
                recv(netfd, hashValue, train.length, MSG_WAITALL);//接受hash
                printf("%s,len=%ld\n",hashValue,strlen(hashValue));//打印
                //hashValue[train.length] = '\0';
                hashValue[strcspn(hashValue, "\n")] = '\0';
                hashValue[strcspn(hashValue, "\t")] = '\0';
                ssize_t ret = quick_send(hashValue, mysql);//验证是否触发秒传
                if(ret == 0)
                {
                    printf("文件已存在。\n");
                    send(netfd, "0", 2, MSG_NOSIGNAL);

                }
                else//文件不存在，要上传
                {
                    printf("正在下载文件...\n");
                    ssize_t ret = recv_file(&stack, hashValue, userName, netfd, mysql);
                    printf ("我是worker,我接受文件完成");
                    if(ret == 0)
                    {
                        send(netfd, "0", 2, MSG_NOSIGNAL);
                        ssize_t ret = check_file_full(&stack, hashValue, fileName, mysql);//上传完校验文件
                        if(ret == 0)
                        {
                            send(netfd, "0", 2, MSG_NOSIGNAL);
                        }
                        else
                        {
                            send(netfd, "-1", 3, MSG_NOSIGNAL);
                        }
                    }
                    else
                    {
                        send(netfd, "-1", 3, MSG_NOSIGNAL);
                    }
                }

            }
            //gets 客户端下载
            else if(train.flag == 4)
            {
                char fileName[1024] = {0};
                memset(&train, 0, sizeof(train));
                recv(netfd, &train.length, sizeof(train.length), MSG_WAITALL);
                recv(netfd, train.data, train.length, MSG_WAITALL);
                strcpy(fileName, train.data);
                ssize_t ret =func_puts(netfd,fileName,&stack, mysql, userName);
                if(ret == 0)
                {
                    send(netfd, "0", 2, MSG_NOSIGNAL);
                }
                else
                {
                    send(netfd, "-1", 3, MSG_NOSIGNAL);
                }

            }

            //remove 删除文件
            else if(train.flag == 5)
            {
                char fileName[1024] = {0};
                memset(&train, 0, sizeof(train));
                recv(netfd, &train.length, sizeof(train.length), MSG_WAITALL);
                recv(netfd, train.data, train.length, MSG_WAITALL);
                strcpy(fileName, train.data);
                ssize_t ret =func_remove(fileName, mysql, &stack);
                if(ret == 0)
                {
                    send(netfd, "0", 2, MSG_NOSIGNAL);
                }
                else
                {
                    send(netfd, "-1", 3, MSG_NOSIGNAL);
                }

            }
            //pwd 展示当前路径
            else if(train.flag == 6)
            {
                ssize_t ret =func_pwd(temp,&stack, mysql);
                if(ret == 0)
                {
                    send(netfd, temp, strlen(temp), MSG_NOSIGNAL);
                }
                else
                {
                    send(netfd, "-1", 3, MSG_NOSIGNAL);
                }

            }
            //mkdir 创建文件夹
            else if(train.flag == 7)
            {
                char fileName[1024] = {0};
                memset(&train, 0, sizeof(train));
                recv(netfd, &train.length, sizeof(train.length), MSG_WAITALL);
                recv(netfd, train.data, train.length, MSG_WAITALL);
                strcpy(fileName, train.data);
                ssize_t ret =func_mkdir(userName,&stack, fileName, mysql);
                if(ret == 0)
                {
                    send(netfd, "0", 2, MSG_NOSIGNAL);
                }
                else
                {
                    send(netfd, "-1", 3, MSG_NOSIGNAL);
                }

            }
            //rmdir 删除文件夹
            else if(train.flag == 8)
            {
                char fileName[1024] = {0};
                memset(&train, 0, sizeof(train));
                recv(netfd, &train.length, sizeof(train.length), MSG_WAITALL);
                recv(netfd, train.data, train.length, MSG_WAITALL);
                strcpy(fileName, train.data);
                ssize_t ret =func_rmdir(&stack,fileName,mysql);
                if(ret == 0)
                {
                    send(netfd, "0", 2, MSG_NOSIGNAL);
                }
                else
                {
                    send(netfd, "-1", 3, MSG_NOSIGNAL);
                }

            }
        }
        close(netfd);
        mysql_close(mysql);
        return NULL;
    }
}


int makeWorker(threadPool_t *pthreadPool)
{
    for(int i = 0; i < pthreadPool->tidArr.workNum; ++i)

    {
        pthread_create(&pthreadPool->tidArr.arr[i],NULL,threadFunc,pthreadPool);
    }
    return 0;
}

